package com.search.service.imp;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import com.search.dao.DocDao;
import com.search.entity.Doc;
import com.search.entity.Search;
import com.search.entity.SearchConfig;
import com.search.entity.SearchConfigEntity;
import com.search.service.SearchService;
import com.search.util.JsonDateValueProcessor;
import com.search.util.PageUtil;
import com.search.util.StringUtil;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;

@Service
@Transactional
public class SearchServiceImpl implements SearchService {
	@Resource
	DocDao d;

	@Resource
	SearchConfig sc;

	@Override
	public String search(HttpServletRequest request, BindingResult bindingResult, Search search, PageUtil page) {
		// 1. 构造返回json
		JSONObject rs = new JSONObject();
		rs.put("data", null);
		rs.put("msg", "操作失败！");
		rs.put("isSuccess", false);

		System.out.println(search.getChannelid() + "");

		// 2. 处理检索类别
		if (StringUtil.isEmpty(search.getChannelid() + "")) {
			search.setChannelid(0);
		} else {
			if (sc.getSearchArray().size() <= search.getChannelid()) {
				search.setChannelid(0);
			}
		}
		System.out.println(sc.toString());

		// 3. 参数验证
		if (bindingResult.hasErrors()) {
			// jdk1.7
			for (int i = 0; i < bindingResult.getAllErrors().size(); i++) {
				FieldError fieldError = (FieldError) bindingResult.getAllErrors().get(i);
				// 属性
				String field = fieldError.getField();
				// 错误信息
				String message = fieldError.getDefaultMessage();
				rs.put("msg", "操作失败！" + field + ":" + message);
			}

			// jdk1.8
			// bindingResult.getAllErrors().forEach((error) -> {
			// FieldError fieldError = (FieldError) error;
			// // 属性
			// String field = fieldError.getField();
			// // 错误信息
			// String message = fieldError.getDefaultMessage();
			// rs.put("msg", "操作失败！" + field + ":" + message);
			// });
			return rs.toString();
		}

		// 4. 查找
		// 4.1 处理时间
		SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmss");
		Calendar calendar = Calendar.getInstance();
		if (search.getTime() != null && !search.getTime().equals("")) {
			if (search.getTime().equals("all")) {
				search.setStarttime("20000101000000");
			} else if (search.getTime().equals("year")) {
				calendar.add(Calendar.DATE, -365);
				search.setStarttime(fmt.format(calendar.getTime()));
			} else if (search.getTime().equals("halfyear")) {
				calendar.add(Calendar.DATE, -180);
				search.setStarttime(fmt.format(calendar.getTime()));
			} else if (search.getTime().equals("month")) {
				calendar.add(Calendar.MONTH, -1);
				search.setStarttime(fmt.format(calendar.getTime()));
			} else if (search.getTime().equals("week")) {
				calendar.add(Calendar.DATE, -7);
				search.setStarttime(fmt.format(calendar.getTime()));
			} else if (search.getTime().equals("date")) {
				calendar.add(Calendar.DATE, -1);
				search.setStarttime(fmt.format(calendar.getTime()));
			}
		}
		if (search.getStarttime() == null || search.getStarttime().equals("")) {
			search.setTime("all");
			search.setStarttime("20000101000000");
		} else {
			try {
				fmt.parse(search.getStarttime());
			} catch (ParseException e) {
				rs.put("msg", "操作失败，开始时间不合法");
				return rs.toString();
			}
		}
		if (search.getEndtime() == null || search.getEndtime().equals("")) {
			search.setEndtime(fmt.format(new Date()));
		} else {
			try {
				fmt.parse(search.getEndtime());
			} catch (ParseException e) {
				rs.put("msg", "操作失败，结束时间不合法");
				return rs.toString();
			}
		}

		// 4.2 处理分页排序
		if (page.getPageCur() == null || page.getPageCur().equals("")) {
			page.setPageCur(0);
		}
		if (page.getPageSize() == null || page.getPageSize().equals("")) {
			page.setPageSize(10);
		}
		Direction direction = Direction.DESC;
		if (page.getOrder() != null && !page.getOrder().isEmpty() && page.getOrder().equals("asc")) {
			direction = Direction.ASC;
		} else {
			page.setOrder("desc");
		}
		Sort sort = new Sort(direction, sc.getSearchArray().get(search.getChannelid()).getSort());
		if (page.getSort() != null && !page.getSort().isEmpty()) {
			String searchsort = page.getSort();
			String searchsorts[] = sc.getSearchArray().get(search.getChannelid()).getSorts().split(",");
			for (String string : searchsorts) {
				if (searchsort.equals(string)) {
					page.setSort(string);
					break;
				} else {
					page.setSort(sc.getSearchArray().get(search.getChannelid()).getSort());
				}
			}
			sort = new Sort(direction, page.getSort());
		} else {
			page.setSort(sc.getSearchArray().get(search.getChannelid()).getSort());
		}
		Pageable pageable = new PageRequest(page.getPageCur(), page.getPageSize(), sort);

		// 4.3 处理检索字段
		if (search.getField() == null || search.getField().equals("")) {
			search.setField(sc.getSearchArray().get(search.getChannelid()).getField());
		} else {
			String searchFiled1[] = search.getField().split(",");
			String searchFileds[] = sc.getSearchArray().get(search.getChannelid()).getFields().split(",");
			ArrayList<String> searchFiled3 = new ArrayList<>();
			for (String string : searchFiled1) {
				for (String string2 : searchFileds) {
					if (string.equals(string2)) {
						searchFiled3.add(string);
					}
				}
			}
			if (searchFiled3.size() == 0) {
				search.setField(sc.getSearchArray().get(search.getChannelid()).getField());
			} else {
				search.setField(String.join(",", searchFiled3.toArray(new String[searchFiled3.size()])));
			}
		}

		long begin = System.currentTimeMillis();
		Page<Doc> goodList = d.findAll(new Specification<Doc>() {
			@Override
			public Predicate toPredicate(Root<Doc> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

				// // 查询条件对象
				// List<Predicate> predicatesAnd = new ArrayList<Predicate>();
				// List<Predicate> predicatesfields = new ArrayList<Predicate>();
				//
				// // 时间
				// try {
				// predicatesAnd.add(cb.between(root.get("docreltime"), fmt.parse(search.getStarttime()), fmt.parse(search.getEndtime())));
				// } catch (ParseException e) {
				// e.printStackTrace();
				// }
				//
				// // 站点
				// if (sc.getSearchArray().get(search.getChannelid()).getSiteid() != null && !sc.getSearchArray().get(search.getChannelid()).getSiteid().equals("")) {
				// In<String> in = cb.in(root.get("siteid"));
				// String siteid[] = sc.getSearchArray().get(search.getChannelid()).getSiteid().split(",");
				// for (String string : siteid) {
				// if (!string.equals("")) {
				// in.value(string);
				// }
				// }
				// predicatesAnd.add(in);
				// }
				//
				// // 栏目
				// if (sc.getSearchArray().get(search.getChannelid()).getChannelid() != null && !sc.getSearchArray().get(search.getChannelid()).getChannelid().equals("")) {
				// In<String> in = cb.in(root.get("channelid"));
				// String channelid[] = sc.getSearchArray().get(search.getChannelid()).getChannelid().split(",");
				// for (String string : channelid) {
				// if (!string.equals("")) {
				// in.value(string);
				// }
				// }
				// predicatesAnd.add(in);
				// }
				//
				// // 检索词
				// String searchFiled[] = search.getField().split(",");
				// String searchWord[] = search.getSearchword().split(",");
				//
				// if (searchFiled.length == searchWord.length) {
				// for (int i = 0; i < searchFiled.length; i++) {
				// predicatesfields.add(cb.like(root.get(searchFiled[i]), "%" + searchWord[i] + "%"));
				// }
				// query.where(cb.and(predicatesfields.toArray(new Predicate[predicatesfields.size()])), cb.and(predicatesAnd.toArray(new Predicate[predicatesAnd.size()])));
				// } else {
				// for (int i = 0; i < searchFiled.length; i++) {
				// for (int j = 0; j < searchWord.length; j++) {
				// predicatesfields.add(cb.like(root.get(searchFiled[i]), "%" + searchWord[j] + "%"));
				// }
				// }
				// query.where(cb.or(predicatesfields.toArray(new Predicate[predicatesfields.size()])), cb.and(predicatesAnd.toArray(new Predicate[predicatesAnd.size()])));
				// }
				return query.getRestriction();

			}
		}, pageable);
		long end = System.currentTimeMillis();

		if (goodList != null) {
			JsonConfig jsonConfig = new JsonConfig(); // 建立配置文件
			jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor("yyyy-MM-dd HH:mm:ss"));
			jsonConfig.setExcludes(new String[] { "user" });
			JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(goodList, jsonConfig);
			jsonObject.put("search", search);
			jsonObject.put("page", page);
			// page.setTotalElements(totalHits);
			jsonObject.put("time", end - begin);

			rs.put("msg", "查询成功！");
			rs.put("isSuccess", true);
			rs.put("data", jsonObject);

			return rs.toString();
		} else {
			rs.put("msg", "查询成功，暂无数据！");
			rs.put("isSuccess", true);
		}
		// 4. 返回结果
		return rs.toString();
	}

	@Override
	public String getSearchArray() {
		// 1. 构造返回json
		JSONObject rs = new JSONObject();
		rs.put("data", null);
		rs.put("msg", "查询失败！");
		rs.put("isSuccess", false);

		// 2. 检索分类查询
		List<SearchConfigEntity> list = sc.getSearchArray();
		if (list != null) {
			JsonConfig jsonConfig = new JsonConfig(); // 建立配置文件
			jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor("yyyy-MM-dd HH:mm:ss"));
			jsonConfig.setExcludes(new String[] { "user" });
			JSONArray jsonObject = (JSONArray) JSONSerializer.toJSON(list, jsonConfig);
			rs.put("msg", "查询成功！");
			rs.put("isSuccess", true);
			rs.put("data", jsonObject);
			return rs.toString();
		} else {
			rs.put("msg", "查询成功，暂无统计信息！");
			rs.put("isSuccess", true);
		}

		// 3. 返回结果
		return rs.toString();
	}

}
